package reference;

import junit.framework.TestCase;
import org.junit.Test;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author bigOrang
 * @date 2021/9/5
 * xxx
 */
public class ThreadLocalLeak extends TestCase {
    private static ThreadLocal<Object> threadLocal = new ThreadLocal<>();


    @Test
    public void testT(){
        System.out.println(8 & 5);
    //    1000
    //    0101

        int x = 8;int y = 5;
        System.out.println(x - y * (x / y));
    }
    /**
     * 假设是tomcat.每次请求都set.其实不会泄露.
     * @throws InterruptedException
     */
    public static void mockThreadPool() throws InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));

        for (int i = 0; i < 10; i++) {
            threadPoolExecutor.execute(() -> {
                //while (true) {
                    threadLocal.set(new byte[1024 * 1024 * 50]);
                    try {
                        Thread.sleep(2000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                //}
            });
            System.out.println("set  " + i);
            Thread.sleep(600L);
        }
        //Thread.sleep(60000L);

/*        for (int i = 0; i < 10; i++) {
            Thread.sleep(500L);
            threadPoolExecutor.execute(() -> {
                int count = 0;
                while (count <= 3) {

                    try {
                        Thread.sleep(2000L);
                        count++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            System.out.println(i);
        }*/


        // set会有清楚nullkey的逻辑.
        threadPoolExecutor.execute(() -> {
            //threadLocal.remove();
            threadLocal.set("clear");
            System.out.println("clear");
        });

        Thread.sleep(3000000L);
    }


    public static void mockLeak() throws InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));

        for (int i = 0; i < 10; i++) {
            threadPoolExecutor.execute(() -> {
                ThreadLocal<Object> threadLocal2 = new ThreadLocal<>();
                threadLocal2.set(new byte[1024 * 1024 * 50]);
                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            System.out.println("set  " + i);
            Thread.sleep(200L);
        }

        for (int i = 0; i < 10; i++) {
            Thread.sleep(500L);
            threadPoolExecutor.execute(() -> {
                int count = 0;
                while (count <= 3) {
                    try {
                        Thread.sleep(1000L);
                        count++;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            System.out.println(i);
        }

        System.out.println("等待15秒,这15秒内无法被gc");
        TimeUnit.SECONDS.sleep(15);


        // set会有清除nullkey的逻辑.不clear也不影响.只是如果没有新的set进来.就会一直不能被回收
/*        for (int i = 0; i < 10; i++) {
            threadPoolExecutor.execute(() -> {
                //threadLocal.remove();
                threadLocal.set("clear");
                System.out.println(Thread.currentThread() + "clear");
                try {
                    Thread.sleep(300L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }*/
        Thread.sleep(3000000L);
    }


    public static void main(String[] args) throws InterruptedException {

        //mockThreadPool();

        mockLeak();
    }
}
